/*
 * Phys2D - a 2D physics engine based on the work of Erin Catto.
 * 
 * This source is provided under the terms of the BSD License.
 * 
 * Copyright (c) 2006, Phys2D
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or 
 * without modification, are permitted provided that the following 
 * conditions are met:
 * 
 *  * Redistributions of source code must retain the above 
 *    copyright notice, this list of conditions and the 
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above 
 *    copyright notice, this list of conditions and the following 
 *    disclaimer in the documentation and/or other materials provided 
 *    with the distribution.
 *  * Neither the name of the Phys2D/New Dawn Software nor the names of 
 *    its contributors may be used to endorse or promote products 
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 */
package de.iritgo.skillfull.component;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;

import de.iritgo.skillfull.collision.CollisionManager;
import de.iritgo.skillfull.collision.MoveListener;
import de.iritgo.skillfull.component.visitor.Visitor;
import de.iritgo.skillfull.config.ConfigManager;
import de.iritgo.skillfull.entity.Entity;


/**
 * The collision component
 * 
 * @author held
 */
public class CollisionComponentImpl extends VisualComponentImpl implements CollisionComponent
{
	/** The col manager */
	private CollisionManager collisionManager;

	/** The config manager */
	private ConfigManager configManager;

	/** The moving listeners...yes we are an observer */
	private List<MoveListener> moveListeners;
	
	/** The size of the box */
	private Rectangle rectangle = new Rectangle ();
	
	/** We are on collision state */
	private boolean markCollision;
	               
	/** Set the config manager */
	public void setConfigManager(ConfigManager configManager) 
	{
		this.configManager = configManager;
	}

	/** Set the col manager */
	public void setCollisionManager (CollisionManager collisionManager)
	{
		this.collisionManager = collisionManager;
	}
	
	public Rectangle getRectangle ()
	{
		return rectangle;
	}

	public void setHeight (int height)
	{
		rectangle.height = height;
	}
	
	@Override
	public int getHeight() 
	{
		return rectangle.height;
	}

	public void setWidth (int width)
	{
		rectangle.width = width;
	}

	@Override
	public int getWidth() 
	{
		return rectangle.width;
	}
	
	@Override
	public void setX (int x) 
	{
		rectangle.x = x;
	}
	
	@Override
	public void setY (int y) 
	{
		rectangle.y = y;
	}
	
	@Override
	public int getX() 
	{
		return rectangle.x;
	}
	
	@Override
	public int getY() 
	{
		return rectangle.y;
	}

	/** Called from spring to init this object */
	public void initialize ()
	{
		moveListeners = new ArrayList<MoveListener> ();
		active = false;
	}
	
	/**
	 * @see de.iritgo.skillfull.component.ComponentImpl#init()
	 */
	public void init ()
	{
		rectangle.x = -100;
		rectangle.y = -100;
		active = false;
	}

	/**
	 * @see de.iritgo.skillfull.component.VisualComponentImpl#accept(de.iritgo.skillfull.component.visitor.Visitor)
	 */
	public void accept (Visitor visitor) 
	{
		visitor.visit (this);
	}

	/**
	 * @see de.iritgo.skillfull.component.CollisionComponent#markCollision(boolean)
	 */
	public void markCollision(boolean markCollision) 
	{
		this.markCollision = markCollision;
	}

	/**
	 * @see de.iritgo.skillfull.component.VisualComponentImpl#printConfiguration()
	 */
	public void printConfiguration() 
	{
	}
	
	/**
	 * @see de.iritgo.skillfull.component.ComponentImpl#deactivate()
	 */
	public void deactivate() 
	{
		collisionManager.remove (this);
		moveListeners.clear ();
		super.deactivate();
	}
	
	/**
	 * @see de.iritgo.skillfull.component.ComponentImpl#removed(de.iritgo.skillfull.entity.Entity)
	 */
	public void removed (Entity entity) 
	{
		collisionManager.remove (this);
		moveListeners.clear ();
		super.removed(entity);
	}

	/**
	 * @see de.iritgo.skillfull.component.CollisionComponent#registerOnCollisionManager()
	 */
	public void registerOnCollisionManager () 
	{
		collisionManager.add (this);
		active = true;
	}

	/**
	 * Check if this box touches another
	 * 
	 * @param other The other box to check against  
	 * @return True if the boxes touches
	 */
	public boolean touches (CollisionComponent other)
	{
		if (! active)
			return false;
		
		if (! rectangle.contains(other.getRectangle ()))
			return rectangle.intersects (other.getRectangle ());
		return true;
	}

	/**
	 * @see de.iritgo.skillfull.component.VisualComponentImpl#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics, de.iritgo.skillfull.entity.Entity)
	 */
	public void render(GameContainer container, Graphics g, Entity entity) 
	{
		if (configManager.functionActive("showCollision"))
		{
			if (markCollision)
			{
				g.setColor(Color.red);
				g.drawRect(rectangle.x + 2, rectangle.y + 2, rectangle.width - 4, rectangle.height - 4);
			}
			g.setColor(Color.white);
		}
		if (configManager.functionActive("showCollisionRange"))
		{
			g.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
		}

	}


	/**
	 * @see de.iritgo.skillfull.component.CollisionComponent#moved()
	 */
	public void moved () 
	{
		ArrayList<MoveListener> copyListeners = new ArrayList<MoveListener> ();
		copyListeners.addAll (moveListeners);
		
		for (MoveListener listener : copyListeners)
		{
			listener.moving (this);
		}
	}

	/**
	 * @see de.iritgo.skillfull.component.CollisionComponent#removeMoveListener(de.iritgo.skillfull.collision.MoveListener)
	 */
	public void removeMoveListener(MoveListener listener) 
	{
		moveListeners.remove (listener);
	}

	/**
	 * @see de.iritgo.skillfull.component.CollisionComponent#addMoveListener(de.iritgo.skillfull.collision.MoveListener)
	 */
	public void addMoveListener(MoveListener listener) 
	{
		moveListeners.add (listener);
	}
}
